package org.scmpatrol.core.scm.timer;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import org.apache.log4j.Logger;
import org.jboss.annotation.ejb.Depends;
import org.scmpatrol.core.scm.SCMRepositoryManager;
import org.scmpatrol.scm.SCMRepository;
import org.scmpatrol.scm.common.exception.SCMPatrolException;

/**
 * This stateless ejb is the timer service which launch the check for update on
 * a given repository.
 * 
 */
@Stateless
@Local(value = RepositoryUpdateScheduler.class)
@Depends(value="jboss.j2ee:ear=ear-0.1-SNAPSHOT.ear,jar=core-0.1-SNAPSHOT.jar,name=SCMRepositoryManagerBean,service=EJB3")
public class RepositoryUpdateSchedulerBean implements RepositoryUpdateScheduler {
	private final static Logger LOGGER = Logger
			.getLogger(RepositoryUpdateSchedulerBean.class.getName());

	private final static Integer DEFAULT_DELAY = 30 * 1000;

	SCMRepositoryManager repositoryManager;
	
	@Resource
	private SessionContext context;

	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public void scheduleRepositoryUpdate(SCMRepository repository) {
		// Launch an update without delay on startup
		scheduleRepositoryUpdate(repository, 0);
	}
	
	private void scheduleRepositoryUpdate(SCMRepository repository, Integer delay) {
		LOGGER.info("Create trigger for execution in " + delay
				+ "ms for repository " + repository);
		context.getTimerService().createTimer(delay, repository);
	}

	@Timeout
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public void triggerHandler(Timer timer) {
		SCMRepository repository = (SCMRepository) timer.getInfo();
		LOGGER.info("It's time to shake " + repository);

		try {
			repositoryManager.updateRepository(repository);

			// We recreate the scheduler only if there is no problems updating
			// the repository.
			// TODO be more fine grained on exception management
			scheduleRepositoryUpdate(repository, DEFAULT_DELAY);
		} catch(SCMPatrolException e) {
			LOGGER.info("There was an error updating the repository " + repository.getUrl() + 
					". Stopping the automatic updates. You must restart the scheduler manually.");
			// TODO add a repository scheduler status to keep trace of this....
		}
		
	}

	@EJB(beanName="SCMRepositoryManagerBean")
	void setRepositoryManager(SCMRepositoryManager repositoryManager) {
		this.repositoryManager = repositoryManager;
	}

}
